Los datos espaciales suelen observarse en entidades poligonales con límites definidos. Los límites de los polígonos son definidos por el investigador, en algunos campos de estudio pueden ser arbitrarios en otros y pueden ser límites administrativos creados con fines muy diferentes en otros. Los datos observados suelen ser agregaciones dentro de los límites, como los recuentos de población. Las entidades territoriales pueden constituir en sí mismas las unidades de observación, por ejemplo cuando se estudia el comportamiento de los gobiernos locales donde las decisiones se toman a nivel de la entidad, por ejemplo, la fijación de los tipos impuestos locales. Sin embargo, en general, las entidades de área son agregados, recipientes, que se utilizan para contabilizar las mediciones, como los resultados de las votaciones en los colegios electorales. Muy a menudo, las entidades de área son una teselación exhaustiva del área de estudio, sin dejar ninguna parte del área total sin asignar a una entidad. Por supuesto, las entidades de área pueden estar formadas por múltiples entidades geométricas, como islas pertenecientes a un mismo condado; también pueden rodear completamente a otras entidades de área por completo, y pueden contener agujeros, como los lagos.
Los límites de las entidades de área pueden definirse con algún otro propósito que su uso en el análisis de datos. Las zonas de código postal pueden ser útiles para el análisis, pero se crearon para facilitar los envíos postales. Sólo recientemente las organizaciones censales nacionales han aceptado que los cambios frecuentes, aparentemente justificados de los límites son un problema importante para los análisis longitudinales. Los límites arbitrarios de las unidades de área son un problema si su modificación puede conducir a resultados diferentes, y el caso del gerrymandering político es un recordatorio aleccionador de cómo los cambios en la agregación pueden cambiar los resultados. También pueden obstaculizar el análisis si la escala espacial o la huella de un proceso de generación de datos subyacente no se corresponde con los límites elegidos.
Si la recopilación de datos puede diseñarse para que las entidades de área coincidan con los datos, se reducirá la influencia de la elección de los agregados. Un ejemplo podría ser la correspondencia de los datos del mercado laboral con los mercados laborales locales, tal vez definidos por los desplazamientos al trabajo. Por otro lado, si nos vemos obligados a utilizar límites arbitrarios, a menudo porque no hay otras fuentes de datos secundarios, debemos ser conscientes de las posibles dificultades. Estos desajustes se encuentran entre las razones para encontrar autocorrelación espacial en el análisis de los agregados de área; otras razones son los procesos espaciales sustanciales en los que las entidades se influyen entre sí por contagio, como la adopción de políticas similares por parte de los vecinos, y la especificación errónea del modelo que deja información con patrones espaciales en los residuos del modelo. Estas causas de la autocorrelación espacial observada pueden de la autocorrelación espacial observada, por lo que la identificación correcta de los procesos espaciales reales es una tarea interesante.
Un amplio rango de disciplinas científicas se ha encontrado con la autocorrelación espacial entre entidades de área, con el término “problema de Galton” utilizado en varias. El problema consiste en establecer cuántas observaciones efectivamente independientes están presentes cuando se han utilizado límites arbitrarios para dividir un área de estudio. En su intercambio con Tyler en 1889, Galton cuestionó si las observaciones de las leyes matrimoniales a través de entidades areales constituían observaciones independientes, ya que sólo podían reflejar un patrón general del todos descienden. Así, la dependencia espacial positiva tiende a reducir la cantidad de información contenida en las observaciones, porque las observaciones próximas pueden utilizarse en parte para predecirse mutuamente.
hemos visto cómo las distancias en una superficie continua pueden utilizarse para estructurar la autocorrelación espacial, por ejemplo con el variograma. Aquí nos ocuparemos de las entidades de área que se definen como vecinos. En una superficie continua, todos los puntos son vecinos de los demás, aunque algunos pueden tener muy poco peso, porque están muy distantes. En una superficie teselada, podemos elegir definiciones de vecinos que dividen el conjunto de todas las entidades (excluyendo la observación i) en miembros o no miembros del conjunto de vecinos de la observación i. También podemos decidir dar a cada relación de vecindad un peso igual, o variar los pesos en los arcos del grafo dirigido que describe la dependencia espacial.
En la siguiente sección se tratará la construcción de los vecinos y los pesos que pueden aplicarse a las vecindades. Una vez establecido este importante y a menudo exigente prerrequisito, pasamos a estudiar las formas de medir la autocorrelación espacial. Aunque las pruebas se basan en modelos de procesos espaciales, primero examinamos pruebas, y después pasamos a la modelización. También nos interesa mostrar cómo se puede introducir la autocorrelación espacial en datos datos independientes, para poder realizar simulaciones. Hay que tener en cuenta que el patrón espacial que encontremos puede indicar únicamente que nuestro modelo actual de los datos no es adecuado. Esto se aplica a las unidades de área que no se ajustan al proceso de de generación de datos, a las variables que faltan, incluidas las que tienen una forma forma funcional incorrecta, y a las diferencias entre nuestras suposiciones sobre los datos y sus distribuciones reales, que a menudo se muestran como una dispersión excesiva en los datos de recuento.
Se utilizará los datos de censo para 8 condados centrales del estado de New York
NY8 <- readOGR("data", "NY8_utm18")
## OGR data source with driver: ESRI Shapefile
## Source: "C:\Users\usuario\OneDrive\Desktop\german\ArealData\data", layer: "NY8_utm18"
## with 281 features
## It has 17 fields
ny <- st_read("data/NY8_utm18.shp")
## Reading layer `NY8_utm18' from data source
## `C:\Users\usuario\OneDrive\Desktop\german\ArealData\data\NY8_utm18.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 281 features and 17 fields
## Geometry type: POLYGON
## Dimension: XY
## Bounding box: xmin: 358241.9 ymin: 4649755 xmax: 480393.1 ymax: 4808545
## Projected CRS: WGS 84 / UTM zone 18N
plot(st_geometry(ny), axes = T)
La creación de pesos espaciales es un paso necesario en el análisis de datos en área. El primer paso es definir cuales relaciones entre las observaciones tendrán pesos no nulos, es decir, escoger el criterio para que dos enlaces sean considerados como “vecinos”; el segundo es asignar los pesos a los enlaces identificados como “vecinos” en el paso anterior.
Crear los vecinos y pesos no es un proceso fácil y por lo tanto
existen varias funciones y métodos en el paquete spdep que
ayudan a realizar este trabajo. El paquete ade4 contiene
las funciones nb2neig() y neig2nb() las cuales
ayudan a transformar objetos entre las clases nb y
neig.
En el paquete spdep las observaciones enlazadas
(vecinas) son objetos de clase nb; dichos objetos pueden
ser vistos como una lista de tamaño \(n\) donde cada elemento contiene un vector
con los indices de sus correspondientes vecinos. Si alguna observación
no tiene vecinos, la entrada correspondiente contiene el valor cero (0).
Estos objetos también contiene otro tipo de atributos como lo puede ser
un vector de caracteres para identificar cada una de las regiones
consideradas, además de un vector lógico (booleano) que indica si una
relación es simétrica o no (se discute más adelante). La función
card() devuelve el número de vecinos para cada elemento de
la lista (objeto nb). A continuación se presenta brevemente
la estructura de estos objetos espaciales:
NY_nb <- read.gal("data/NY_nb.gal", # read.gal carga el archivo de clase nb
region.id = as.numeric(row.names(ny)) - 1
) # Debe empezar en 0
summary(NY_nb)
## Neighbour list object:
## Number of regions: 281
## Number of nonzero links: 1522
## Percentage nonzero weights: 1.927534
## Average number of links: 5.41637
## Link number distribution:
##
## 1 2 3 4 5 6 7 8 9 10 11
## 6 11 28 45 59 49 45 23 10 3 2
## 6 least connected regions:
## 55 97 100 101 244 245 with 1 link
## 2 most connected regions:
## 34 82 with 11 links
plot(st_geometry(ny), border = "grey60", axes = T)
plot(NY_nb, st_geometry(ny), pch = 19, cex = 0.6, add = T)
Un archivo gal es una matriz de pesos o vecinos
producida por el software GeoDa. Para esta situación particular, todas
las regiones contiguas son consideradas como regiones vecinas.
Luego de ilustrar los datos espaciales que van a ser tratados, se
usará un subconjunto de ellos para mostrar el uso de las principales
funciones y métodos para los objetos nb; el subconjunto a
usar corresponde a Syracuse city.
Syracuse <- filter(ny, AREANAME == "Syracuse city")
Sy0_nb <- subset(NY_nb, ny$AREANAME == "Syracuse city")
plot(st_geometry(Syracuse), border = "grey60", axes = T)
plot(Sy0_nb, st_geometry(Syracuse), pch = 19, cex = 0.6, add = T)
Los principales métodos de los objetos nb son
print(), summary() y plot(), sin
embargo, no son los únicos que existen.
Tanto print como summary presentan el
número de regiones, enlaces no nulos, porcentaje de pesos no nulos y
promedio de enlaces entre regiones, sin embargo, summary
presenta adicionalmente la distribución del número de enlaces del objeto
nb, además de las regiones con menor y mayor frecuencia de
enlaces dentro del objeto.
summary(Sy0_nb)
## Neighbour list object:
## Number of regions: 63
## Number of nonzero links: 346
## Percentage nonzero weights: 8.717561
## Average number of links: 5.492063
## Link number distribution:
##
## 1 2 3 4 5 6 7 8 9
## 1 1 5 9 14 17 9 6 1
## 1 least connected region:
## 164 with 1 link
## 1 most connected region:
## 136 with 9 links
Adicionalmente, el método summary también reporta la
presencia o no de asimetría en el objeto nb
La asimetria está presente cuando i es un vecino de j, pero j no es un vecino de i.
El resultados del método summary brinda la siguiente
información:
Se observa también la distribución de las relaciones que indican que el número máximo de vecinos que se encontraron fueron 9 y estuvieron con respecto a un poligono, 17 de las 63 regiones presentes tienen 6 uniones, etc.
La función card permite obtener de forma rápida el
número de vecinos de cada región.
card(Sy0_nb)
## [1] 5 5 2 7 7 5 4 5 7 5 5 7 5 7 6 6 6 6 6 4 4 7 6 8 4 3 3 9 6 8 6 6 6 8 6 4 4 8
## [39] 6 6 7 5 7 6 4 5 3 5 6 4 6 7 4 8 5 1 5 8 5 5 6 3 3
Se crearán objetos de lista de vecinos para uso posterior en el
documento, para esto se utiliza la función knearneigh para
obtener el índice de los puntos de \(k\) vecinos cercanos, esta función recibe
como parametro de ingreso la lista de coordenadas de los puntos y un
valor \(k\) que indica el número de
puntos vecinos cercanos que se desean retornar. El resultado de la
operación anterior se ingresa a la función knn2nb para
convertir el objeto resultante en una lista de vecinos de la clase
nb.
coords <- st_point_on_surface(st_geometry(Syracuse))
ids <- row.names(Syracuse)
Sy8_nb <- knn2nb(knearneigh(coords, k = 1), row.names = ids)
Sy8_nb
## Neighbour list object:
## Number of regions: 63
## Number of nonzero links: 63
## Percentage nonzero weights: 1.587302
## Average number of links: 1
## Non-symmetric neighbours list
la función nbdists obtiene las distancias entre los
puntos de los objectos vecinos calculados en el paso anterior. Esto es
util porque con ella se obtiene la distancia minima necesaria
para asegurar que todas las áreas tengan al menos un
vecino.
Posteriormente se utiliza la función dnearneigh para
obtener la lista de objetos vecinos (nb) que se encuentran a una
determinada distancia (d1, d2).
dsts <- unlist(nbdists(Sy8_nb, coords))
Sy11_nb <- dnearneigh(x = coords, d1 = 0, d2 = 0.75 * max(dsts))
Sy11_nb
## Neighbour list object:
## Number of regions: 63
## Number of nonzero links: 156
## Percentage nonzero weights: 3.930461
## Average number of links: 2.47619
## 8 regions with no links:
## 1 10 20 36 46 57 60 61
Como resultado, se observa que existen 8 regiones que no poseen vecinos (1, 10, 20…).
La literatura respecto a los pesos espaciales es muy pequeña, lo cual resulta sorprendente teniendo en cuenta la gran importancia que tienen los pesos espaciales al momento de medir y modelar dependencia espacial para datos en área.
Los pesos espaciales se pueden ver como una lista de pesos indexados por una lista de vecinos, donde el peso de la relación entre \(i\) e \(j\) es el \(k\)-ésimo elemento del \(i\)-ésimo componente de la lista de pesos.
Una vez definida la lista de vecinos espaciales, el próximo paso es asignar pesos espaciales a cada uno de los enlaces entre regiones. En caso de conocer características importante del proceso espacial que se este tratando, dicha información puede ser útil al momento de asignarle pesos a los enlaces, de lo contrario es mejor evitarlo para evadir problemas de mala especificación del mismo.
La función nb2listw toma un objeto de lista de vecinos
(nb) y lo convierte en un objeto de pesos. La conversión
por defecto es W, donde los pesos varían entre la unidad
dividido por el más largo y el más pequeño número de vecinos y la suma
de los pesos para cada entidad de área es la unidad.
Sy0_lw_w <- nb2listw(neighbours = Sy0_nb)
Sy0_lw_w
## Characteristics of weights list object:
## Neighbour list object:
## Number of regions: 63
## Number of nonzero links: 346
## Percentage nonzero weights: 8.717561
## Average number of links: 5.492063
##
## Weights style: W
## Weights constants summary:
## n nn S0 S1 S2
## W 63 3969 63 24.78291 258.564
Otro tipo de conversión se obtiene al configurar style = B, con lo cual se obtiene un peso de 1 por cada relación vecina y 0 en otro caso, pero en esta situación, la suma de los pesos para áreas difieren de acuerdo al número de vecinos que las áreas tengan.
Se recomienda utilizar pesos binarios cuando se tiene poco conocimiento acerca del proceso que se está estudiando.
El argumento glist puede ser usado para asignar manualmente
los pesos a cada enlace entre regiones del objeto nb; como
se mencionó previamente, esto puede ser útil en situaciones donde se
tiene información respecto a las posibles relaciones que pueden existir
entre dos regiones, lo cual podría ayudar a obtener mejores resultados.
A continuación se presenta un ejemplo suponiendo que los pesos obedecen
a la regla IDW binaria (inverso de las distancias entre regiones)
dsts <- nbdists(Sy0_nb, coords)
idw <- lapply(dsts, function(x) 1 / (x / 1000))
Sy0_lw_idwB <- nb2listw(Sy0_nb, glist = idw, style = "B")
summary(unlist(Sy0_lw_idwB$weights))
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.3062 0.7481 0.9547 1.0154 1.2232 2.7686
summary(sapply(Sy0_lw_idwB$weights, sum))
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.321 4.129 5.896 5.577 6.967 9.860
A continuación se presentan 3 tipos de pesos espaciales:
Sy0_lw_B <- nb2listw(Sy0_nb, style = "B")
pal <- brewer.pal(9, "Reds")
oopar <- par(mfrow = c(1, 3), mar = c(1, 1, 3, 1) + 0.1)
z <- t(listw2mat(Sy0_lw_w))
brks <- c(0, 0.1, 0.143, 0.167, 0.2, 0.5, 1)
nbr3 <- length(brks) - 3
image(1:63, 1:63, z[, ncol(z):1],
breaks = brks,
col = pal[c(1, (9 - nbr3):9)],
main = "W style", axes = FALSE
)
box()
z <- t(listw2mat(Sy0_lw_B))
image(1:63, 1:63, z[, ncol(z):1],
col = pal[c(1, 9)], main = "B style",
axes = FALSE
)
box()
z <- t(listw2mat(Sy0_lw_idwB))
brks <- c(0, 0.35, 0.73, 0.93, 1.2, 2.6)
nbr3 <- length(brks) - 3
image(1:63, 1:63, z[, ncol(z):1],
breaks = brks,
col = pal[c(1, (9 - nbr3):9)],
main = "IDW B style", axes = FALSE
)
box()
par(oopar)
El último argumento a considerar en la función
nb2listw() es zero.policy. Cuando existen regiones
sin vecinos es necesario especificar el argumento
zero.policy = T para que no arroje error, esto debido a que
por defecto la función nb2listw() asume que cada región
tiene al menos un vecino.
try(
expr = {
nb2listw(neighbours = Sy11_nb, style = "B", zero.policy = F)
}
)
## Error in nb2listw(neighbours = Sy11_nb, style = "B", zero.policy = F) :
## Empty neighbour sets found
Luego de especificar como verdadero dicho argumento, se obtiene el resultado sin fallas computacionales
Sy0_lw_D1 <- nb2listw(neighbours = Sy11_nb, style = "B", zero.policy = T)
print(Sy0_lw_D1, zero.policy = T)
## Characteristics of weights list object:
## Neighbour list object:
## Number of regions: 63
## Number of nonzero links: 156
## Percentage nonzero weights: 3.930461
## Average number of links: 2.47619
## 8 regions with no links:
## 1 10 20 36 46 57 60 61
##
## Weights style: B
## Weights constants summary:
## n nn S0 S1 S2
## B 55 3025 156 312 2240
Ahora que se tienen una serie de formas de construir pesos espaciales, podemos empezar a utilizarlas para comprobar la presencia de autocorrelación espacial. Antes de hacer algo serio, sería muy útil revisar los supuestos de las pruebas; utilizaremos la I de Moran como ejemplo, pero las consecuencias se aplican también a otras pruebas.
Hay dos tipos de test de autocorrelación espacial que se aplican a este tipo de datos:
Es la forma más común de abordar la autocorrelación espacial. Se calcula como la razón del producto de la variable de interés y su rezago espacial, con el producto cruzado de la variable de interés y ajustada por los pesos espaciales usados.
\[I = \frac{n}{\sum_{i=1}^{n} \sum_{j=1}^{n} w_{ij}}\ \frac{\sum_{i=1}^{n} \sum_{j=1}^{n} (y_i - \bar{y})(y_j - \bar{y})}{\sum_{i=1}^{n} (y_i - \bar{y})^2}\] donde:
Centrarse en la media es equivalente a afirmar que el modelo correcto tiene una media constante, y que cualquier patrón restante después del centrado es causado por las relaciones espaciales codificadas en los pesos espaciales.
Para esto, se calcula la esperanza como:
\[E(I) = \frac{-1}{n-1}\]
El siguiente paso es tomar el valor observado y restarlo al valor esperado analíticamente (I - E(I)) para finalmente dividirlo por la raíz cuadrada de la varianza analítica. El resultado es comparado con la distribución normal para encontrar el valor de probabilidad del estadístico observado bajo la hipótesis nula de ausencia de dependencia espacial para los pesos espaciales elegidos. Los resultados pueden depender de la elección de las ponderaciones, de los vecindarios y de que los supuestos sean cumplidos.
\[H_0: Ausencia \ de \ dependencia \ espacial\] \[H_1: El \ estadístico \ observado \ es \ significativamente \ más \ grande \ que \ el \ valor \ esperado\]
El dominio del I de Moran es [-1, 1]. Se evidencia autocorrelación espacial positiva cuando I > 0. Esto quiere decir que las unidades de análisis vecinas tienden a ser similares.
moran.test(x = ny$Cases, listw = nb2listw(NY_nb))
##
## Moran I test under randomisation
##
## data: ny$Cases
## weights: nb2listw(NY_nb)
##
## Moran I statistic standard deviate = 3.9778, p-value = 3.477e-05
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic Expectation Variance
## 0.146882990 -0.003571429 0.001430595
Por defecto, el moran.test usa el supuesto de
aleatorización lo que difiere del supuesto de normalidad más simple al
introducir un término de corrección basado en la curtosis de la variable
de interés. Cuando la curtosis corresponde a la de una variable con
distribución normal, las dos suposiciones arrojan la misma varianza,
pero a medida que la variable se aleja de la normalidad, la suposición
de aleatorización compensa aumentando la varianza y disminuyendo la
desviación estándar.
moran.test(x = ny$Cases, listw = nb2listw(NY_nb), randomisation = F)
##
## Moran I test under normality
##
## data: ny$Cases
## weights: nb2listw(NY_nb)
##
## Moran I statistic standard deviate = 3.9731, p-value = 3.547e-05
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic Expectation Variance
## 0.146882990 -0.003571429 0.001433975
En este caso, se observa que la varianza no cambia, por lo tanto, el supuesto de normalidad se cumple.
Es posible también realizar test de Monte Carlo para evaluar la hipótesis de dependencia espacial con el test de Moran I.
moran.mc(x = ny$Cases, listw = nb2listw(NY_nb), nsim = 999)
##
## Monte-Carlo simulation of Moran I
##
## data: ny$Cases
## weights: nb2listw(NY_nb)
## number of simulations + 1: 1000
##
## statistic = 0.14688, observed rank = 1000, p-value = 0.001
## alternative hypothesis: greater
Waller y Gotway (2004, p. 231) también incluyen un riesgo constante de Poisson parametrico para evaluar la importancia de la autocorrelación en los recuentos de casos. La tasa global constante \(r\) se calcula primero y se utiliza para crear los recuentos esperados para cada tramo censal multiplicando por la población.
lw_B <- nb2listw(NY_nb, style = "B")
r <- sum(NY8$Cases)/sum(NY8$POP8)
rni <- r * NY8$POP8
CR <- function(var, mle) rpois(length(var), lambda = mle)
MoranI.pboot <- function(var, i, listw, n, S0, ...) {
return(moran(x = var, listw = listw, n = n, S0 = S0)$I)
}
set.seed(1234)
boot2 <- boot(NY8$Cases, statistic = MoranI.pboot,
R = 999, sim = "parametric", ran.gen = CR,
listw = lw_B, n = length(NY8$Cases), S0 = Szero(lw_B),
mle = rni)
pnorm((boot2$t0 - mean(boot2$t))/sd(boot2$t[, 1]), lower.tail = FALSE)
## [1] 0.1472112
Los conteos esperados también pueden expresarse como los valores ajustados de una regresión de Poisson con un desplazamiento ajustado al logaritmo de la población del tramo, esto muestra la relación con los modelos lineales generalizados (como los casos no son todos enteros, se generan advertencias):
Los recuentos esperados rni se introducen en el
argumento lambda a rpois para generar los conjuntos de
datos sintéticos mediante el muestreo de la distribución de Poisson. El
valor de la probabilidad de salida se calcula a partir del mismo I de
Moran observado menos la media de los valores I simulados, y se divide
por su desviación estándar.
# Monte Carlo test
set.seed(1234)
bperm <- moran.mc(NY8$Cases, listw=lw_B, nsim=999)
bperm
##
## Monte-Carlo simulation of Moran I
##
## data: NY8$Cases
## weights: lw_B
## number of simulations + 1: 1000
##
## statistic = 0.11039, observed rank = 1000, p-value = 0.001
## alternative hypothesis: greater
r <- sum(NY8$Cases)/sum(NY8$POP8)
rni <- r*NY8$POP8
CR <- function(var, mle) rpois(length(var), lambda=mle)
MoranI.pboot <- function(var, i, listw, n, S0, ...) {
return(moran(x=var, listw=listw, n=n, S0=S0)$I)
}
set.seed(1234)
boot2 <- boot(NY8$Cases, statistic=MoranI.pboot, R=999, sim="parametric",
ran.gen=CR, listw=lw_B, n=length(NY8$Cases), S0=Szero(lw_B), mle=rni)
pnorm((boot2$t0 - mean(boot2$t))/sd(boot2$t[,1]), lower.tail=FALSE)
## [1] 0.1472112
oopar <- par(mfrow=c(1,2))
xlim <- range(c(bperm$res, boot2$t[,1]))
hist(bperm$res[-length(bperm$res)], main="Permutation bootstrap", xlab=expression(I[std]), xlim=xlim, density=15, angle=45, ylim=c(0,260))
abline(v=bperm$statistic, lty=2)
hist(boot2$t, col=rgb(0.4,0.4,0.4), main="Parametric bootstrap", xlab=expression(I[CR]), xlim=xlim, ylim=c(0,260))
hist(bperm$res[-length(bperm$res)], density=15, angle=45, add=TRUE)
abline(v=boot2$t0, lty=2)
par(oopar)
Los resultados de los índices de Bayes empírico sugieren que una razón para la de la falta de significación del bootstrap paramétrico del riesgo constante observado y los valores esperados podría ser que los valores inusuales y extremos se observaron en tramos con poblaciones pequeñas. Una vez que las tasas han sido suavizadas, se encuentra cierta autocorrelación global.
Conociendo las medidas globales de asociación espacial, es posible descomponer estas medidas con el fin de construir test locales que buscan detectar clusters (Observaciones con vecinos muy similares) y hotspots (Observaciones con vecinos muy diferentes), además se pueden utilizar para conocer el impacto de los estadísticos individuales en sus contrapartes globales.
(Anselin, 1995)
Cualquier estadístico que cumplas las siguientes condiciones:
Comprobar si la contribución local a la agrupación en torno a la observación i es significativamente diferente de 0, identificando localidades donde existe un grado significativo de agrupación espacial.
Partiendo del índice global de Moran:
\[ I = \frac{n}{\sum_{i=1}^{n} \sum_{j=1}^{n} w_{ij}}\ \frac{\sum_{i=1}^{n} \sum_{j=1}^{n} (y_i - \bar{y})(y_j - \bar{y})}{\sum_{i=1}^{n} (y_i - \bar{y})^2} \]
Se reescribe le ecuación en:
\[ I = n \left[ \sum_k \sum_j w_{kj} \right]^{-1}\left[ \sum_k (y_k-\bar{y})^2 \right]^{-1} \sum_i I_i \]
donde:
\[ I_i = (y_i-\bar{y}) \sum_j w_{ij} (y_j - \bar{y}) \]
Como:
\(n \left[ \sum_k \sum_j w_{kj} \right]^{-1}\left[ \sum_k (y_k-\bar{y})^2 \right]^{-1}\) no depende de i, entonces para un conjunto dado de \(z_i\) esta expresión se comporta como una constante.
\[ I = cte \cdot \sum_i I_i \]
Reemplazando \(z6_i = y_i - \bar{y}\) se obtiene la expresión original propuesta por Anselin, 1995.
\[ I_i = z_i \sum_j w_{ij}z_j \]
\(I_i\) es el producto de \(z_i\) y la media de los valores \(z_j\) de los vecinos del polígono \(i\)
Finalmente, para cada \(I_i\) se puede aplicar un test de significancia estadística con una hipótesis nula de ausencia de asociación espacial.
Cuadrantes de asociación espacial. Modificado de Siabato et al., 2018
Antes de presentar la construcción del diagrama de dispersión de Moran, se presenta brevemente la definición de los rezagos espaciales, necesarios para la construcción de la gráfica ya mencionada.
Luego de tener definida la estructura de pesos en la matriz \(W\), los rezagos espaciales se definen como el producto entre la matriz de pesos y el valor de la variable de interés \(y\). En pocas palabras, un rezago espacial es una suma de valores de los vecinos ponderada espacialmente. (Applications of Spatial Weights)
\[ Wy \] Esta operación está bien definida puesto que \(W \in \mathbb{R}^{n\times n}\) y \(y \in \mathbb{R}^{n \times 1}\).
En la práctica está operación suele hacerse como:
\[ [Wy]_i = \sum_{j=1}^n w_{ij}y_j \] lo cual es equivalente a la operación matricial definida previamente, sin embargo, como en la vida real se suele trabajar con grandes tamaños de muestra, guardar la matriz \(W\) como una “matriz pura” puede resultar en un gran desperdicio de memoria y sus valores suelen ser guardados en una “sparse matrix”.
El gráfico de dispersión de Moran por convención posiciona la variable de interés en el eje x y los valores de rezago espacial en el eje y. El índice global de Moran es una relación lineal entre estos valores y es dibujado como la pendiente.
(ggplot(moran_plot, aes(x, wx)) +
geom_point(aes(shape = is_inf, color = is_inf), size = 0.75) +
scale_color_manual(values = c("black", "red")) +
geom_hline(
yintercept = moran_plot$wx %>% mean(),
linetype = "dashed", alpha = 0.5
) +
geom_vline(
xintercept = moran_plot$x %>% mean(),
linetype = "dashed", alpha = 0.5
) +
geom_text(aes(x, wx, label = labels),
data = filter(moran_plot, is_inf),
size = 2.5
) +
geom_smooth(method = "lm", se = F, size = .6, col = "black") +
labs(
x = "Cases", y = "Spatial lagged cases",
title = "Moran Scatterplot",
shape = "Significativo", color = "Significativo"
) +
theme_bw() +
theme(plot.title = element_text(hjust = 0.5))) %>%
plotly::ggplotly()
El gráfico se divide en 4 cuadrantes. El cuadrante de la esquina superior derecha indica áreas que tienen un alta incidencia de casos de leucemia y están rodeadas por otras áreas que tienen nivel superior al promedio de casos (high-high). En la esquina inferior izquierda se encuentran áreas con baja incidencia de casos de leucemia rodeadas por áreas con incidencia de leucemia por debajo del promedio (low-low). Las áreas high-high son conocidas como hotspots y las áreas low-low como coldspots. En la diagonal opuesta se tienen valores atípicos espaciales, que indica que son áreas que están rodeadas por vecinos muy diferentes a ellos.
Al igual que en el caso de la estadística global, se puede comprobar la divergencia de los estadísticos locales de los valores esperados, bajo los supuestos de normalidad y aleatoriedad analíticamente y usando métodos como el de punto de silla y exacto.
local <- as.data.frame(localmoran(ny$Cases,
listw = nb2listw(NY_nb, style = "C")
))
local2 <- as.data.frame(localmoran.sad(lm(Cases ~ 1, ny),
nb = NY_nb, style = "C"
))
local3 <- as.data.frame(localmoran.exact(lm(Cases ~ 1, ny), nb = NY_nb, style = "C"))
ny %>%
select(Cases) %>%
mutate(
p_value = moran_plot$is_inf,
rezago = lag.listw(nb2listw(NY_nb, style = "B"), Cases),
cuadrante = case_when(
(Cases > mean(Cases)) & (rezago > mean(rezago)) &
(p_value == T) ~ "High-High",
(Cases <= mean(Cases)) & (rezago <= mean(rezago)) &
(p_value == T) ~ "Low-Low",
(Cases > mean(Cases)) & (rezago <= mean(rezago)) &
(p_value == T) ~ "High-Low",
(Cases <= mean(Cases)) & (rezago > mean(rezago)) &
(p_value == T) ~ "Low-High",
TRUE ~ "NS"
),
index = moran_plot$labels
) -> resultados
resultados_coords <- filter(resultados, p_value == T) %>%
mutate(
x = (st_centroid(resultados$geometry) %>% st_coordinates())[1],
y = (st_centroid(resultados$geometry) %>% st_coordinates())[2]
)
(ggplot(resultados) +
geom_sf(aes(fill = cuadrante), alpha = 0.8) +
scale_fill_manual(values = viridisLite::viridis(5)) +
labs(
title = "Lugares con influencia de Leucemia \n",
x = "Longitud", y = "Latitud"
) +
geom_sf_text(
data = resultados_coords,
mapping = aes(x, y, label = index),
color = "white"
) +
theme_bw() +
theme(
plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
axis.text = element_blank(),
axis.ticks = element_blank()
)) %>%
plotly::ggplotly()
Se puede calcular una evaluación de riesgo constante asumiendo una distribución Poisson con un valor de \(\lambda\) igual a la probabilidad de ocurrencia de la enfermedad, se estandariza la variable tomando la propiedad de que tanto la media como la desviación estandar son iguales en esta distribución, se calculan los rezagos y se compara el indice de morán actual con el de riesgo constante.
ny %>%
transmute(
p_afectada = sum(Cases) / sum(POP8) * POP8,
casos_std = (Cases - p_afectada) / sqrt(p_afectada),
rezago = stats::lag(nb2listw(NY_nb, style = "C"), casos_std),
indice_riesgo = casos_std * rezago,
indice = local$Ii
) -> riesgo
m_riesgo <- ggplot(riesgo) +
geom_sf(aes(fill = indice_riesgo)) +
labs(title = "Mapa de riesgo Constante") +
scale_fill_gradientn(
colours = viridisLite::viridis(20,
begin = 0.17,
end = 0.98
),
limits = c(-2.2, 3.7)
) +
theme_bw() +
theme(
plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
axis.text = element_blank(),
axis.ticks = element_blank()
)
m_actual <- ggplot(riesgo) +
geom_sf(aes(fill = indice)) +
labs(title = "Mapa de riesgo Standard") +
scale_fill_gradientn(
colours = viridisLite::viridis(20,
begin = 0.17,
end = 0.98
),
limits = c(-2.2, 3.7)
) +
theme_bw() +
theme(
plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
axis.text = element_blank(),
axis.ticks = element_blank()
)
cowplot::plot_grid(m_actual, m_riesgo, align = "hv", ncol = 2)
# set.seed(1234)
# nsim <- 999
# N <- length(rni)
# sims <- matrix(0, ncol = nsim, nrow = N)
# for (i in 1:nsim) {
# y <- rpois(N, lambda = rni)
# sdCRi <- (y - rni)/sqrt(rni)
# wsdCRi <- lag(lw, sdCRi)
# sims[, i] <- sdCRi * wsdCRi
# }
# xrank <- apply(cbind(I_CR, sims), 1, function(x) rank(x)[1])
# diff <- nsim - xrank
# diff <- ifelse(diff > 0, diff, 0)
# pval <- punif((diff + 1)/(nsim + 1))
monte_carlo_sim <- function(nsim, prop, Ii, nb) {
N <- length(prop)
sims <- matrix(0, ncol = nsim, nrow = N)
for (i in 1:nsim) {
y <- rpois(N, lambda = prop)
z <- (y - prop) / sqrt(prop)
rezago <- stats::lag(nb2listw(nb, style = "C"), z)
sims[, i] <- z * rezago
}
xrank <- apply(cbind(Ii, sims), 1, function(x) rank(x)[1])
diff <- nsim - xrank
diff <- ifelse(diff > 0, diff, 0)
pval <- punif((diff + 1) / (nsim + 1))
return(pval)
}
mc_sim <- riesgo %>%
select(p_afectada, indice_riesgo) %>%
mutate(
pvalue_cr = monte_carlo_sim(
999, p_afectada,
indice_riesgo, NY_nb
),
pvalue_sad = local2$`Pr. (Sad)`,
pvalue_exact = local3$`Pr. (exact)`,
pvalue_rand = local$`Pr(z != E(Ii))`,
pvalue_norm = local2$`Pr. (N)`
) %>%
pivot_longer(
cols = c(
"pvalue_cr", "pvalue_sad",
"pvalue_exact", "pvalue_rand", "pvalue_norm"
),
names_to = "type", values_to = "p_value"
) %>%
mutate(discrete = cut(p_value,
breaks = c(
0, 0.05, 0.1,
0.9, 0.95, 1, max(p_value)
),
include.lowest = T
))
aux_labs <- c(
"pvalue_cr" = "Riesgo constante",
"pvalue_exact" = "Exacto",
"pvalue_norm" = "Normal",
"pvalue_rand" = "Aleatorio",
"pvalue_sad" = "Saddlepoint"
)
ggplot(mc_sim) +
geom_sf() +
geom_sf(aes(fill = discrete),
data = filter(mc_sim, p_value < 0.1 | p_value > 0.9 &
p_value < 1)
) +
facet_wrap(~type, labeller = labeller(type = aux_labs)) +
labs(title = "") +
scale_fill_manual(values = viridisLite::viridis(5), name = "P-value") +
theme_bw() +
theme(
plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
axis.text = element_blank(),
axis.ticks = element_blank()
)
En este gráfico podemos verificar asumiendo distintas distribuciones para determinar si un área es atipica o de agrupación y esto nos sirve para verificar si los indices observados tienen sustento estadístico para tener mas peso de sustentarlo.
La dependencia espacial se puede modelar de diferentes formas por medio de modelos estadísticos, probablemente se piense en algunos supuestos como la independencia entre observaciones o distribución pero no es el caso de datos espaciales pero se puede explicar la autocorrelación espacial entre áreas vecinas pero si el vector de variables respuesta se distribuye normal multivariado se puede expresar de la siguiente manera:
\[ Y=\mu + e, \]
Una transformación que se recomiendo es una logaritmica que incluya los pesos en nuestro caso la cantidad de población para considerar un riesgo heterogéneo y una de las alternativas es:
\[ Z_i=log \left( \frac{1000(Y_i+1)}{n_i}\right) \]
TCE <- readOGR("data", "TCE")
## OGR data source with driver: ESRI Shapefile
## Source: "C:\Users\usuario\OneDrive\Desktop\german\ArealData\data", layer: "TCE"
## with 11 features
## It has 5 fields
ny <- readOGR("data",'NY8_utm18')
## OGR data source with driver: ESRI Shapefile
## Source: "C:\Users\usuario\OneDrive\Desktop\german\ArealData\data", layer: "NY8_utm18"
## with 281 features
## It has 17 fields
nylm <- lm(Z~PEXPOSURE+PCTAGE65P+PCTOWNHOME, data=ny)
summary(nylm)
##
## Call:
## lm(formula = Z ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME, data = ny)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.7417 -0.3957 -0.0326 0.3353 4.1398
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.51728 0.15856 -3.262 0.00124 **
## PEXPOSURE 0.04884 0.03506 1.393 0.16480
## PCTAGE65P 3.95089 0.60550 6.525 3.22e-10 ***
## PCTOWNHOME -0.56004 0.17031 -3.288 0.00114 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.6571 on 277 degrees of freedom
## Multiple R-squared: 0.1932, Adjusted R-squared: 0.1844
## F-statistic: 22.1 on 3 and 277 DF, p-value: 7.306e-13
Con los datos en área se usa el centroide de cada poligono y se asignan varias covariables para crear un modelo de regresión lineal para explicar la variable Z, este es un ejemplo considerando 3 covariables.
ny$lmresid <- residuals(nylm) # residuales modelo sin pesos
NYlistw <- nb2listw(NY_nb, style = "B")
lm.morantest(nylm, NYlistw)
##
## Global Moran I for regression residuals
##
## data:
## model: lm(formula = Z ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME, data = ny)
## weights: NYlistw
##
## Moran I statistic standard deviate = 2.638, p-value = 0.004169
## alternative hypothesis: greater
## sample estimates:
## Observed Moran I Expectation Variance
## 0.083090278 -0.009891282 0.001242320
Suponiendo que se ha eliminado la tendencia de la variable de interés y que las ponderaciones espaciales están estandarizadas por filas, el estimador de un paso del parámetro de regresión espacial puede producir más información comparativa que el I de Moran. A modo de comparación, mostramos la estimación del parámetro de máxima verosimilitud ajustada utilizando los mismos datos:
NYlistwW <- nb2listw(NY_nb, style = "W")
aple(residuals(nylm), listw=NYlistwW)
## [1] 0.2051536
spautolm(Z~PEXPOSURE+PCTAGE65P+PCTOWNHOME, data=ny, listw=NYlistwW)$lambda
## lambda
## 0.2169261
nysar <- spautolm(Z~PEXPOSURE+PCTAGE65P+PCTOWNHOME, data=ny, listw=NYlistw)
summary(nysar)
##
## Call: spautolm(formula = Z ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME, data = ny,
## listw = NYlistw)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.56754 -0.38239 -0.02643 0.33109 4.01219
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.618193 0.176784 -3.4969 0.0004707
## PEXPOSURE 0.071014 0.042051 1.6888 0.0912635
## PCTAGE65P 3.754200 0.624722 6.0094 1.862e-09
## PCTOWNHOME -0.419890 0.191329 -2.1946 0.0281930
##
## Lambda: 0.040487 LR test value: 5.2438 p-value: 0.022026
## Numerical Hessian standard error of lambda: 0.017199
##
## Log likelihood: -276.1069
## ML residual variance (sigma squared): 0.41388, (sigma: 0.64333)
## Number of observations: 281
## Number of parameters estimated: 6
## AIC: 564.21
Con los resultados obtenidos se observa que existe una correlación en los residuales por que el valor estimado de \(\lambda\) es 0.0405 y el valor p es 0.022. en la prueba de máxima verosimilitud aunque el parámetro sea significativo a un nivel de confianza del 95% pero es bueno verificar con otro tipo de modelo para no descartar una posible asociación.
Por otro lado la covariable exposición no es significativa.
nylam1 <- c(nysar$lambda)
nylam2 <- c(LR1.Spautolm(nysar)$p.value)
ny$sar_trend <- nysar$fit$signal_trend
ny$sar_stochastic <- nysar$fit$signal_stochastic
rds <- colorRampPalette(brewer.pal(8, "RdBu"))
tr_at <- seq(-1, 1.3, length.out=21)
tr_rds <- rds(sum(tr_at >= 0)*2)[-(1:(sum(tr_at >= 0)-sum(tr_at < 0)))]
tr_pl <- spplot(ny, c("sar_trend"), at=tr_at, col="transparent", col.regions=tr_rds, main=list(label="Trend", cex=0.8))
st_at <- seq(-0.16, 0.39, length.out=21)
st_rds <- rds(sum(st_at >= 0)*2)[-(1:(sum(st_at >= 0)-sum(st_at < 0)))]
st_pl <- spplot(ny, c("sar_stochastic"), at=st_at, col="transparent", col.regions=st_rds, main=list(label="Stochastic", cex=0.8))
plot(tr_pl, split=c(1,1,2,1), more=TRUE)
plot(st_pl, split=c(2,1,2,1), more=FALSE)
Recordemos que este modelo no tiene en cuenta la distribución heterogénea de la población, es decir, considera que la población es igual en cada zona por esto se incluye al modelo lm al argumento weights = POP8.
nylmw <- lm(Z~PEXPOSURE+PCTAGE65P+PCTOWNHOME, data=ny, weights=POP8)
summary(nylmw)
##
## Call:
## lm(formula = Z ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME, data = ny,
## weights = POP8)
##
## Weighted Residuals:
## Min 1Q Median 3Q Max
## -129.067 -14.714 5.817 25.624 70.723
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.77837 0.14116 -5.514 8.03e-08 ***
## PEXPOSURE 0.07626 0.02731 2.792 0.00560 **
## PCTAGE65P 3.85656 0.57126 6.751 8.60e-11 ***
## PCTOWNHOME -0.39869 0.15305 -2.605 0.00968 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 33.5 on 277 degrees of freedom
## Multiple R-squared: 0.1977, Adjusted R-squared: 0.189
## F-statistic: 22.75 on 3 and 277 DF, p-value: 3.382e-13
ny$lmwresid <- residuals(nylmw)
Añadiendo la ponderación de pesos se observa que la covariable exposición si es significativa que difiere con el modelo anterior, pues tiene sentido que exista un relación entre los casos de leucemia y el nivel de exposición.
lm.morantest(nylmw, NYlistw)
##
## Global Moran I for regression residuals
##
## data:
## model: lm(formula = Z ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME, data = ny,
## weights = POP8)
## weights: NYlistw
##
## Moran I statistic standard deviate = 0.4773, p-value = 0.3166
## alternative hypothesis: greater
## sample estimates:
## Observed Moran I Expectation Variance
## 0.007533246 -0.009309771 0.001245248
Los resultados son interesantes, sugiriendo que la mala especificación detectada por el I de Moran está de hecho relacionada con la heteroscedasticidad más que a la autocorrelación espacial.
nysarw <- spautolm(Z ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME,
data = ny, listw = NYlistw, weights = POP8)
summary(nysarw)
##
## Call: spautolm(formula = Z ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME, data = ny,
## listw = NYlistw, weights = POP8)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.48488 -0.26823 0.09489 0.46552 4.28343
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.797063 0.144054 -5.5331 3.146e-08
## PEXPOSURE 0.080545 0.028334 2.8428 0.004473
## PCTAGE65P 3.816731 0.576037 6.6258 3.453e-11
## PCTOWNHOME -0.380778 0.156507 -2.4330 0.014975
##
## Lambda: 0.0095636 LR test value: 0.32665 p-value: 0.56764
## Numerical Hessian standard error of lambda: 0.016466
##
## Log likelihood: -251.6017
## ML residual variance (sigma squared): 1104.1, (sigma: 33.229)
## Number of observations: 281
## Number of parameters estimated: 6
## AIC: 515.2
no hay rastros de espacio. autocorrelación que queda después de ajustar por el tamaño heterogéneo de la población
gry <- c(rev(brewer.pal(6, "Reds")[1:4]), colorRampPalette(brewer.pal(5, "Blues"))(9))
TCEpts <- list("sp.points", TCE, pch=16, col="grey5")
spplot(ny, c("lmresid", "lmwresid"), sp.layout=list(TCEpts), col.regions=gry, col="transparent", lwd=0.5, at=seq(-2,4.5,0.5))
Se observa en pequeños poligonos que el modelo con ponderación se obtiene resudiales mas pequeños que con le modelo sin los pesos.
ny$sarw_trend <- nysarw$fit$signal_trend
ny$sarw_stochastic <- nysarw$fit$signal_stochastic
tr_pl <- spplot(ny, c("sarw_trend"), at=tr_at, col="transparent", col.regions=tr_rds, main=list(label="Trend", cex=0.8))
st_pl <- spplot(ny, c("sarw_stochastic"), at=st_at, col="transparent", col.regions=st_rds, main=list(label="Stochastic", cex=0.8))
plot(tr_pl, split=c(1,1,2,1), more=TRUE)
plot(st_pl, split=c(2,1,2,1), more=FALSE)
Esto sugiere que la variación espacial en la población entre tractos es responsable de la correlación espacial residual observada después de ajustar por covariables.
La especificación CAR se basa en la distribución condicional de la distribución de los errores que se expresa de la siguiente manera:
\[ e_i | e_{j \sim \: i } \sim N \left( \sum_{j \sim i } \frac{c_{ij}e_j }{\sum_{j\sim i }c_{ij} }, \frac{\sim^{2}_{e_i} }{\sum_{j\sim i }c_{ij} } \right ) \]
donde \(e_{j\sim i }\) representa los vecinos del área i y \(c_{ij}\) son parámetros dependientes de \(b_{ij}\).
Al final se obtiene que:
\[ E[Y] =X^T\beta \\ Var(Y) =\sigma^2(1-\lambda W )^{-1}(1-\lambda W^T )^{-1} \]
nycar <- spautolm(Z~PEXPOSURE+PCTAGE65P+PCTOWNHOME , data=ny, family="CAR",listw=NYlistw)
summary(nycar)
##
## Call: spautolm(formula = Z ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME, data = ny,
## listw = NYlistw, family = "CAR")
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.539732 -0.384311 -0.030646 0.335126 3.808848
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.648362 0.181129 -3.5796 0.0003442
## PEXPOSURE 0.077899 0.043692 1.7829 0.0745986
## PCTAGE65P 3.703830 0.627185 5.9055 3.516e-09
## PCTOWNHOME -0.382789 0.195564 -1.9574 0.0503053
##
## Lambda: 0.084123 LR test value: 5.8009 p-value: 0.016018
## Numerical Hessian standard error of lambda: 0.030868
##
## Log likelihood: -275.8283
## ML residual variance (sigma squared): 0.40758, (sigma: 0.63842)
## Number of observations: 281
## Number of parameters estimated: 6
## AIC: 563.66
Aunque la estimación de los parámetros sean similares a los del modelo SAR los valores de p de dos covariables, la distancia al TCE más cercano y el porcentaje de personas ser propietario de una vivienda, son mayores a un 0.05 asumiendo un nivel de confianza del 95% y aparte la prueba de verosimilitud nos dice que existe una autocorrelación espacial significativa. Esto sin considerar los pesos ponderados de POP8.
nylam1 <- c(nycar$lambda)
nycarw <- spautolm(Z~PEXPOSURE+PCTAGE65P+PCTOWNHOME, data=ny, family="CAR",listw=NYlistw, weights=POP8)
summary(nycarw)
##
## Call: spautolm(formula = Z ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME, data = ny,
## listw = NYlistw, weights = POP8, family = "CAR")
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.491042 -0.270906 0.081435 0.451556 4.198134
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.790154 0.144862 -5.4545 4.910e-08
## PEXPOSURE 0.081922 0.028593 2.8651 0.004169
## PCTAGE65P 3.825858 0.577720 6.6223 3.536e-11
## PCTOWNHOME -0.386820 0.157436 -2.4570 0.014010
##
## Lambda: 0.022419 LR test value: 0.38785 p-value: 0.53343
## Numerical Hessian standard error of lambda: 0.038543
##
## Log likelihood: -251.5711
## ML residual variance (sigma squared): 1102.9, (sigma: 33.21)
## Number of observations: 281
## Number of parameters estimated: 6
## AIC: 515.14
Para este caso con la misma metodologia aplicando los pesos se observa que las tres covariables son significativas ya que el p valor obtenido es muy pequeño.
La función spautolm ajusta los modelos de regresión espacial por máxima verosimilitud, encontrando el coeficiente autoregresivo para que maximiza la función de verosimilitud para la familia de modelos elegida, y luego ajustando los otros coeficientes por mínimos cuadrados generalizados en ese punto. Esto significa que el coeficiente autorregresivo espacial se puede encontrar mediante la búsqueda de líneas utilizando optimizar, en lugar de optimizar sobre todos los parámetros del modelo en el Mismo tiempo. Se llega a la siguiente expresión:
\[ log(|I-\lambda W|)=log \left( \prod_{i=1}^n (1-\lambda \zeta_i) \right) \]
Donde $ _i$ son los valores propios de \(W\).
nysarwM <- spautolm(Z~PEXPOSURE+PCTAGE65P+PCTOWNHOME, data=ny,family="SAR",listw=NYlistw, weights=POP8, method="Matrix")
summary(nysarwM)
##
## Call: spautolm(formula = Z ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME, data = ny,
## listw = NYlistw, weights = POP8, family = "SAR", method = "Matrix")
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.48488 -0.26823 0.09489 0.46552 4.28343
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.797063 0.144054 -5.5331 3.146e-08
## PEXPOSURE 0.080545 0.028334 2.8428 0.004473
## PCTAGE65P 3.816730 0.576037 6.6258 3.453e-11
## PCTOWNHOME -0.380777 0.156507 -2.4330 0.014975
##
## Lambda: 0.0095636 LR test value: 0.32665 p-value: 0.56764
## Numerical Hessian standard error of lambda: 0.013835
##
## Log likelihood: -251.6017
## ML residual variance (sigma squared): 1104.1, (sigma: 33.229)
## Number of observations: 281
## Number of parameters estimated: 6
## AIC: 515.2
nysar_ll <- spautolm(Z~PEXPOSURE+PCTAGE65P+PCTOWNHOME, data=ny, family="SAR",listw=NYlistw, llprof=100)
nysarw_ll <- spautolm(Z~PEXPOSURE+PCTAGE65P+PCTOWNHOME, data=ny, family="SAR",listw=NYlistw, weights=POP8, llprof=100)
ylim <- range(c(nysarw_ll$llprof$ll, nysar_ll$llprof$ll), na.rm=TRUE)
plot(nysarw_ll$llprof$lambda, nysarw_ll$llprof$ll, type="l", xlab=expression(lambda), ylab="log likelihood", ylim=ylim, lwd=2)
abline(v=nysarw_ll$lambda)
abline(h=nysarw_ll$LL)
lines(nysar_ll$llprof$lambda, nysar_ll$llprof$ll, lty=2, lwd=2)
abline(v=nysar_ll$lambda, lty=2)
abline(h=nysar_ll$LL, lty=2)
legend("bottom", legend=c("weighted SAR", "SAR"), lty=c(1,2), lwd=2, bty="n")
En este gráfico se muestra la función de log verosimilitud en función de \(\lambda\) y donde alcanza su máximo.
1/range(eigenw(NYlistw))
## [1] -0.3029200 0.1549552
nysmaw <- spautolm(Z~PEXPOSURE+PCTAGE65P+PCTOWNHOME, data=ny, family="SMA",listw=NYlistw, weights=POP8)
summary(nysmaw)
##
## Call: spautolm(formula = Z ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME, data = ny,
## listw = NYlistw, weights = POP8, family = "SMA")
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.487080 -0.268990 0.093956 0.466055 4.284087
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.795243 0.143749 -5.5321 3.163e-08
## PEXPOSURE 0.080153 0.028237 2.8386 0.004531
## PCTAGE65P 3.820316 0.575463 6.6387 3.165e-11
## PCTOWNHOME -0.382529 0.156160 -2.4496 0.014302
##
## Lambda: 0.0091843 LR test value: 0.30771 p-value: 0.57909
## Numerical Hessian standard error of lambda: 0.016571
##
## Log likelihood: -251.6112
## ML residual variance (sigma squared): 1105.3, (sigma: 33.245)
## Number of observations: 281
## Number of parameters estimated: 6
## AIC: 515.22
Lo interesante de análisis de datos espaciales es la amplia gama de disciplinas involucradas, ya que esto se le puede dar multiples enfoques en esto cado para terminos ecónomicos.
Pues es de interes como bienes raíz, información financiera e indicadores ecónomicos que se pueden crear.
La econometría espacial es descrita por Anselin (1988, 2002), y autorizadamente avanzado por LeSage y Pace (2009), con comentarios adicionales de Bivand (2002, 2006) con respecto a hacer econometría espacial en R.
Como vimos anteriormente los datos se trataban de problemas epidemeológicos en el caso de econometria se propone diferentes supuestos como el área de econometria es algo complejo y no se cuenta con buenos conomientos en esa área y no es algo a lo que le vamos a dar mucha relevancia comentaremos algunas cosas pequeñas ya que algunas librerias no se encuentran en el CRAN por lo que presentamos problemas.
Se pueden utilizar otros metodos para explciar la correlación espacial como los GAM donde asumimos una distribución que no necesariamente es una normal.
ny$x <- coordinates(ny)[, 1]/1000
ny$y <- coordinates(ny)[, 2]/1000
nyGAM1 <- gam(Z ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME +
s(x, y), weights = POP8, data = ny)
anova(nylmw, nyGAM1, test = "Chisq")
## Analysis of Variance Table
##
## Model 1: Z ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME
## Model 2: Z ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME + s(x, y)
## Res.Df RSS Df Sum of Sq Pr(>Chi)
## 1 277.00 310778
## 2 273.19 305229 3.8096 5549.7 0.2671
En este caso esto no agrega valor a los modelos que ya vimos anteriormente.
nyGLMp <- glm(Cases ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME +
offset(log(POP8)), data = NY8, family = "poisson")
summary(nyGLMp)
##
## Call:
## glm(formula = Cases ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME + offset(log(POP8)),
## family = "poisson", data = NY8)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.6779 -1.0570 -0.1984 0.6326 3.2655
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -8.13442 0.18261 -44.545 < 2e-16 ***
## PEXPOSURE 0.14893 0.03121 4.773 1.82e-06 ***
## PCTAGE65P 3.99816 0.59783 6.688 2.27e-11 ***
## PCTOWNHOME -0.35710 0.19027 -1.877 0.0605 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for poisson family taken to be 1)
##
## Null deviance: 428.25 on 280 degrees of freedom
## Residual deviance: 353.35 on 277 degrees of freedom
## AIC: Inf
##
## Number of Fisher Scoring iterations: 5
Hay poca sobredispersión presente - ajuste con la familia poisson en el que el parámetro de dispersión no se fija en la unidad, por lo que pueden modelar una dispersión excesiva que no da como resultado grandes cambios.
nyGAMp <- gam(Cases ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME + offset(log(POP8)) + s(x, y), data = ny, family = "poisson")
summary(nyGAMp)
##
## Family: poisson
## Link function: log
##
## Formula:
## Cases ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME + offset(log(POP8)) +
## s(x, y)
##
## Parametric coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -8.13659 0.21475 -37.889 < 2e-16 ***
## PEXPOSURE 0.16807 0.05985 2.808 0.00498 **
## PCTAGE65P 3.71993 0.64308 5.785 7.27e-09 ***
## PCTOWNHOME -0.36019 0.19940 -1.806 0.07087 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Approximate significance of smooth terms:
## edf Ref.df Chi.sq p-value
## s(x,y) 7.708 10.71 9.989 0.504
##
## R-sq.(adj) = 0.394 Deviance explained = 21.4%
## UBRE = 0.2815 Scale est. = 1 n = 281
anova(nyGLMp, nyGAMp, test = "Chisq")
## Analysis of Deviance Table
##
## Model 1: Cases ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME + offset(log(POP8))
## Model 2: Cases ~ PEXPOSURE + PCTAGE65P + PCTOWNHOME + offset(log(POP8)) +
## s(x, y)
## Resid. Df Resid. Dev Df Deviance Pr(>Chi)
## 1 277.00 353.35
## 2 269.29 336.68 7.7079 16.666 0.02907 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1